package com.ihaituan.util;

import java.io.Serializable;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;

@SuppressWarnings("static-access")
public class DateUtil implements Serializable {

    private static final long serialVersionUID = 1L;

    protected DateUtil() {
    }

    public static final String FMT_YYYY = "yyyy";

    public static final String FMT_Y_M = "yyyy-MM";

    public static final String FMT_Y_M_D = "yyyy-MM-dd";

    public static final String FMT_Y_M_D_CN = "yyyy年M月d日";

    public static final String FMTYMD = "yyyyMMdd";

    public static final String FMT_H_M = "HH:mm";

    public static final String FMT_Y_M_D_H_M = "yyyy-MM-dd HH:mm";

    public static final String FMT_Y_M_D_H_M_S = "yyyy-MM-dd HH:mm:ss";

    public static final String FMT_Y_M_D_H_M_S_NEW = "yyyy MM dd HH:mm:ss";

    public static final String FMT_Y_M_D_H_M_S_SSS = "yyyy-MM-dd HH:mm:ss.SSS";

    public static final String FMT_M_D_H = "M月d日H点";

    public static final String FMT_yyyyMMddHHmmss = "yyyyMMddHHmmss";

    /**
     * 日期转字符串 出错者抛出异常
     * @param date
     * @param formateType
     * @return
     */
    public static String dateToString(Date date, String formateType) {
        return format(date, formateType);
    }

    /**
     * 长整型转日期格式字符串
     * @param lon
     * @param formateType
     * @return
     */
    public static String longToDateString(Long lon, String formateType) {
        return format(lon, formateType);
    }

    /**
     * 字符串转日期 出错者抛出异常
     * @param dateStr
     * @param formateType
     * @return
     */
    public static Date stringToDate(String dateStr, String formateType) {
        return parse(dateStr, formateType);
    }

    /**
     * 返回预设Format的当前日期字符串
     * @return
     */
    public static String getToday() {
        Date today = new Date();
        return format(today);
    }

    /**
     * 使用预设Format格式化Date成FMT_Y_M_D
     * @param date
     * @return
     */
    public static String format(Date date) {
        return date == null ? "" : format(date, FMT_Y_M_D);
    }

    /**
     * 获取今天的开始时刻。
     */
    public static Date getTodayStartTime() {
        Calendar cal = Calendar.getInstance();
        cal.set(Calendar.HOUR_OF_DAY, 0);
        cal.set(Calendar.MINUTE, 0);
        cal.set(Calendar.SECOND, 0);
        cal.set(Calendar.MILLISECOND, 0);
        return cal.getTime();
    }

    /**
     * 使用预设Format格式化Date成FMT_Y_M_D_H_M_S
     * @param mils
     * @return
     */
    public static String format(long mils) {
        return format(new Date(mils), FMT_Y_M_D_H_M_S);
    }

    /**
     * 使用参数Format格式化Date成字符串
     * @param date
     * @param pattern
     * @return
     */
    public static String format(Date date, String pattern) {
        return date == null ? "" : new SimpleDateFormat(pattern).format(date);
    }

    /**
     * 使用参数Format格式化Date成字符串
     * @param mils
     * @param pattern
     * @return
     */
    public static String format(long mils, String pattern) {
        return format(new Date(mils), pattern);
    }

    /**
     * 使用预设格式将字符串转为Date
     * @param strDate
     * @return
     * @throws ParseException
     */
    public static Date parse(String strDate) {
        return StringUtil.isEmpty(strDate) ? null : parse(strDate, FMT_Y_M_D);
    }

    /**
     * 使用参数Format将字符串转为Date
     * @param strDate
     * @param pattern
     * @return
     * @throws ParseException
     */
    public static Date parse(String strDate, String pattern) {
        try {
            return StringUtil.isEmpty(strDate) ? null : new SimpleDateFormat(
                    pattern).parse(strDate);
        } catch (ParseException e) {
            e.printStackTrace();
            return null;
        }
    }

    /**
     * 在日期上增加数个整年
     * @param date
     * @param n
     * @return
     */
    public static Date addYear(Date date, int n) {
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        cal.add(Calendar.YEAR, n);
        return cal.getTime();
    }

    /**
     * 在日期上增加数个整月
     * @param date
     * @param n
     * @return
     */
    public static Date addMonth(Date date, int n) {
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        cal.add(Calendar.MONTH, n);
        return cal.getTime();
    }

    /**
     * 在日期上增加数个整天
     * @param date
     * @param n
     * @return
     */
    public static Date addDay(Date date, int n) {
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        cal.add(Calendar.DATE, n);
        return cal.getTime();
    }

    /**
     * 取当天开始时间，如2016年9月1日0点0分0秒
     * @param date 日期
     * @return 当日开始时间
     */
    public static Date getDayStart(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.set(Calendar.HOUR_OF_DAY, 0);
        calendar.set(Calendar.MINUTE, 0);
        calendar.set(Calendar.SECOND, 0);
        calendar.set(Calendar.MILLISECOND, 0);
        return calendar.getTime();
    }

    /**
     * 取当日正午12点时间，如2016年9月1日12点0分0秒
     * @param date 日期
     * @return 当日正午12点
     */
    public static Date getDayNoon(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.set(Calendar.HOUR_OF_DAY, 12);
        calendar.set(Calendar.MINUTE, 0);
        calendar.set(Calendar.SECOND, 0);
        calendar.set(Calendar.MILLISECOND, 0);
        return calendar.getTime();
    }

    /**
     * 获取original所在时间的上季度的开始<br>
     * 如:2013-07-01 00:00:00.000
     * @param original 参照时间
     * @return
     */
    public static long getPreviousQuarterStart(long original) {
        // 本季度开始-1000L得到了上季度范围的时间,再次以这个为参照物,取季度开始时间
        return getQuarterStart(getQuarterStart(original) - 1000L);
    }

    /**
     * 获取original所在时间的上季度的结束<br>
     * 如:2013-07-01 00:00:00.000
     * @param original 参照时间
     * @return
     */
    public static long getPreviousQuarterEnd(long original) {
        // 本季度开始-1000L得到了上季度范围的时间,再次以这个为参照物,取季度结束时间
        return getQuarterEnd(getQuarterStart(original) - 1000L);
    }

    /**
     * 获取在original所在的时间点的上个月的第一天
     * @param original
     * @return
     */
    public static Date getPreviousMonthStart(long original) {
        Date firstDateOfCurrMonth = DateUtil.getFirstDateOfMonth(new Date(original));
        return DateUtil.addMonth(firstDateOfCurrMonth, -1);
    }

    /**
     * 获取在original所在的时间点的上个月的最后一天
     * @param original
     * @return
     */
    public static Date getPreviousMonthEnd(long original) {
        Date firstDateOfCurrMonth = DateUtil.getFirstDateOfMonth(new Date(original));
        return DateUtil.addDay(firstDateOfCurrMonth, -1);
    }

    /**
     * 获取时间戳original在当年的季度(1/2/3/4)
     * @param original
     * @return
     */
    public static int getQuarterIndex(long original) {
        int quarterIndex = 0;
        Calendar calendar = Calendar.getInstance();
        calendar.setTimeInMillis(original);
        int thisMonth = calendar.get(Calendar.MONTH) + 1;
        if (thisMonth >= 1 && thisMonth <= 3) {
            // 当前在1季度
            quarterIndex = 1;
        } else if (thisMonth >= 4 && thisMonth <= 6) {
            // 当前在2季度
            quarterIndex = 2;
        } else if (thisMonth >= 7 && thisMonth <= 9) {
            // 当前在3季度
            quarterIndex = 3;
        } else if (thisMonth >= 10 && thisMonth <= 12) {
            // 当前在4季度
            // 下一年1月
            quarterIndex = 4;
        }
        return quarterIndex;
    }

    /**
     * 获取original所在时间的下季度的开始<br>
     * 如:2013-07-01 00:00:00.000
     * @param original 参照时间
     * @return
     */
    public static long getNextQuarterStart(long original) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTimeInMillis(original);
        int thisMonth = calendar.get(Calendar.MONTH) + 1;
        if (thisMonth >= 1 && thisMonth <= 3) {
            // 当前在1季度
            calendar.set(Calendar.MONTH, 3);
        } else if (thisMonth >= 4 && thisMonth <= 6) {
            // 当前在2季度
            calendar.set(Calendar.MONTH, 6);
        } else if (thisMonth >= 7 && thisMonth <= 9) {
            // 当前在3季度
            calendar.set(Calendar.MONTH, 9);
        } else if (thisMonth >= 10 && thisMonth <= 12) {
            // 当前在4季度
            // 下一年1月
            calendar.add(calendar.YEAR, 1);
            calendar.set(Calendar.MONTH, 0);
        }
        // 设置到1号
        calendar.set(calendar.DATE, 1);
        calendar.set(calendar.HOUR_OF_DAY, 0);
        calendar.set(calendar.MINUTE, 0);
        calendar.set(calendar.SECOND, 0);
        calendar.set(calendar.MILLISECOND, 0);
        return calendar.getTimeInMillis();
    }

    /**
     * 获取original这个时所对应的时间的所属季度（1~4）
     * @param original
     * @return 1~4
     */
    public static int getQuarterNumber(long original) {
        int quarter = -1;
        Calendar calendar = Calendar.getInstance();
        calendar.setTimeInMillis(original);
        int thisMonth = calendar.get(Calendar.MONTH) + 1;
        if (thisMonth >= 1 && thisMonth <= 3) {
            // 1季度
            quarter = 1;
        } else if (thisMonth >= 4 && thisMonth <= 6) {
            // 2季度
            quarter = 2;
        } else if (thisMonth >= 7 && thisMonth <= 9) {
            // 3季度
            quarter = 3;
        } else if (thisMonth >= 10 && thisMonth <= 12) {
            // 4季度
            quarter = 4;
        }
        return quarter;
    }

    /**
     * 获取original所在季度的开始<br>
     * 如:2013-04-01 00:00:00.000
     * @param original 参照时间
     * @return
     */
    public static long getQuarterStart(long original) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTimeInMillis(original);
        int thisMonth = calendar.get(Calendar.MONTH) + 1;
        if (thisMonth >= 1 && thisMonth <= 3) {
            calendar.set(Calendar.MONTH, 0);
        } else if (thisMonth >= 4 && thisMonth <= 6) {
            calendar.set(Calendar.MONTH, 3);
        } else if (thisMonth >= 7 && thisMonth <= 9) {
            calendar.set(Calendar.MONTH, 6);
        } else if (thisMonth >= 10 && thisMonth <= 12) {
            calendar.set(Calendar.MONTH, 9);
        }
        // 设置到1号
        calendar.set(calendar.DATE, 1);
        calendar.set(calendar.HOUR_OF_DAY, 0);
        calendar.set(calendar.MINUTE, 0);
        calendar.set(calendar.SECOND, 0);
        calendar.set(calendar.MILLISECOND, 0);
        return calendar.getTimeInMillis();
    }

    /**
     * 获取original所在季度的结束
     * @param original 参照时间
     * @return
     */
    public static long getQuarterEnd(long original) {
        return getNextQuarterStart(original) - 1L;
    }

    /**
     * 在日期上增加数个小时
     * @param date
     * @param n
     * @return
     */
    public static Date addHour(Date date, int n) {
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        cal.add(Calendar.HOUR_OF_DAY, n);
        return cal.getTime();
    }

    /**
     * 在日期上增加数个分钟
     * @param date
     * @param n
     * @return
     */
    public static Date addMinute(Date date, int n) {
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        cal.add(Calendar.MINUTE, n);
        return cal.getTime();
    }

    /**
     * 得到两个日期时间的差额
     * @param date
     * @param otherDate
     * @return
     */
    public static long betDate(Date date, Date otherDate) {
        return date.getTime() - otherDate.getTime();
    }

    /**
     * 以年，月，日来构造一个日期对象
     * @param year
     * @param month
     * @param day
     * @return
     */
    public static Date makeDate(int year, int month, int day) {
        Calendar calendar = Calendar.getInstance();
        calendar.set(1, year);
        calendar.set(2, month - 1);
        calendar.set(5, day);
        calendar.set(11, 0);
        calendar.set(12, 0);
        calendar.set(13, 0);
        calendar.set(14, 0);
        return calendar.getTime();
    }

    /**
     * 以年，月，日，小时，分钟，秒来构造一个日期对象
     * @param year
     * @param month
     * @param day
     * @param hour
     * @param minute
     * @param second
     * @return
     */
    public static Date makeDate(int year, int month, int day, int hour,
                                int minute, int second) {
        Calendar calendar = Calendar.getInstance();
        calendar.set(1, year);
        calendar.set(2, month - 1);
        calendar.set(5, day);
        calendar.set(11, hour);
        calendar.set(12, minute);
        calendar.set(13, second);
        calendar.set(14, 0);
        return calendar.getTime();
    }

    /**
     * 返回指定日期是哪一月
     * @param date
     * @return
     */
    public static int getMonth(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        return calendar.get(2) + 1;
    }

    /**
     * 返回指定日期是哪一年
     * @param date
     * @return
     */
    public static int getYear(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        return calendar.get(Calendar.YEAR);
    }

    /**
     * 返回指定日期是哪一天
     * @param date
     * @return
     */
    public static int getDay(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        return calendar.get(5);
    }

    /**
     * 返回指定日期是周几
     * @param date
     * @return
     */
    public static int getWeek(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        int week = calendar.get(Calendar.DAY_OF_WEEK);

        if (week == 1)
            return 7;
        else
            return week - 1;

    }

    /**
     * 返回指定日期是几点
     * @param date
     * @return
     */
    public static int getHour(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        return calendar.get(Calendar.HOUR_OF_DAY);

    }

    /**
     * 获得更定日期所在月的最后一天,可能29,30,31,28等
     * @param date
     * @return
     */
    public static Date getLastDateOfMonth(Date date) {
        int year = getYear(date);
        int month = getMonth(date);
        return addDay(addMonth(makeDate(year, month, 1), 1), -1);

    }

    /**
     * 获得指定日期所在月的的第一天
     * @param date
     * @return
     */
    public static Date getFirstDateOfMonth(Date date) {
        int year = getYear(date);
        int month = getMonth(date);
        return makeDate(year, month, 1);
    }

    /**
     * 先得到指定日期所在周,再得到当周指定周几的日期,resultWeek用于指定周几,取值范围1-7
     * @param date
     * @param resultWeek
     * @return
     */
    public static Date getDayOfWeek(Date date, int resultWeek) {
        if (resultWeek < 1 || resultWeek > 7)
            throw new IllegalArgumentException("resultWeek must in 1-7");
        int week = getWeek(date);
        return addDay(date, resultWeek - week);
    }

    /**
     * 得到指定日期一个月有几天
     * @param date 目标日期
     * @return
     */
    public static int getDayNumOfMonth(Date date) {
        Calendar c = Calendar.getInstance();
        c.setTime(date);
        return c.getActualMaximum(Calendar.DATE);
    }

    /**
     * 得到以当前时间为基数的序列<br>
     * yyyyMMddHHmmssS格式的时间
     * @return
     */
    public static Long getTime() {
        Long result = new Long(format(new Date(), "yyyyMMddHHmmssS"));
        return result;
    }

    /**
     * 只把original修改到1970年，其他不变
     * @param original
     * @return
     */
    public static long goto1970(long original) {
        return goYear(original, 1970);
    }

    /**
     * 只把original修改到1970年，其他不变
     * @param original
     * @return
     */
    public static long goYear(long original, int targetYears) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTimeInMillis(original);
        Integer currentYear = Integer.parseInt(format(new Date(original),
                "yyyy"));
        calendar.add(calendar.YEAR, targetYears - currentYear);
        return calendar.getTimeInMillis();
    }

    public static long getNextDay(long original) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTimeInMillis(original);
        calendar.add(calendar.DATE, 1);
        calendar.set(calendar.HOUR_OF_DAY, 0);
        calendar.set(calendar.MINUTE, 0);
        calendar.set(calendar.SECOND, 0);
        calendar.set(calendar.MILLISECOND, 0);
        return calendar.getTimeInMillis();
    }

    public static long getNextWeek(long original) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTimeInMillis(original);
        calendar.add(calendar.DATE, 8);
        calendar.set(calendar.HOUR_OF_DAY, 0);
        calendar.set(calendar.MINUTE, 0);
        calendar.set(calendar.SECOND, 0);
        calendar.set(calendar.MILLISECOND, 0);
        return calendar.getTimeInMillis();
    }

    public static long getNextTwoWeek(long original) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTimeInMillis(original);
        calendar.add(calendar.DATE, 15);
        calendar.set(calendar.HOUR_OF_DAY, 0);
        calendar.set(calendar.MINUTE, 0);
        calendar.set(calendar.SECOND, 0);
        calendar.set(calendar.MILLISECOND, 0);
        return calendar.getTimeInMillis();
    }

    public static long getNextThreeWeek(long original) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTimeInMillis(original);
        calendar.add(calendar.DATE, 22);
        calendar.set(calendar.HOUR_OF_DAY, 0);
        calendar.set(calendar.MINUTE, 0);
        calendar.set(calendar.SECOND, 0);
        calendar.set(calendar.MILLISECOND, 0);
        return calendar.getTimeInMillis();
    }

    public static long getNextMonth(long original) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTimeInMillis(original);
        calendar.add(calendar.MONTH, 1);
        calendar.add(calendar.DATE, 1);
        calendar.set(calendar.HOUR_OF_DAY, 0);
        calendar.set(calendar.MINUTE, 0);
        calendar.set(calendar.SECOND, 0);
        calendar.set(calendar.MILLISECOND, 0);
        return calendar.getTimeInMillis();
    }

    public static long getNextTwoMonth(long original) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTimeInMillis(original);
        calendar.add(calendar.MONTH, 2);
        calendar.add(calendar.DATE, 1);
        calendar.set(calendar.HOUR_OF_DAY, 0);
        calendar.set(calendar.MINUTE, 0);
        calendar.set(calendar.SECOND, 0);
        calendar.set(calendar.MILLISECOND, 0);
        return calendar.getTimeInMillis();
    }

    /**
     * 把当前时间移到三个月后：如当前2013-5-27-->2013-8-27
     * @param original
     * @return
     */
    public static long getNextThreeMonth(long original) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTimeInMillis(original);
        calendar.add(calendar.MONTH, 3);
        calendar.add(calendar.DATE, 1);
        calendar.set(calendar.HOUR_OF_DAY, 0);
        calendar.set(calendar.MINUTE, 0);
        calendar.set(calendar.SECOND, 0);
        calendar.set(calendar.MILLISECOND, 0);
        return calendar.getTimeInMillis();
    }

    public static long getHalfYear(long original) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTimeInMillis(original);
        calendar.add(calendar.MONTH, 6);
        calendar.add(calendar.DATE, 1);
        calendar.set(calendar.HOUR_OF_DAY, 0);
        calendar.set(calendar.MINUTE, 0);
        calendar.set(calendar.SECOND, 0);
        calendar.set(calendar.MILLISECOND, 0);
        return calendar.getTimeInMillis();
    }

    public static long getNextYear(long original) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTimeInMillis(original);
        calendar.add(calendar.YEAR, 1);
        calendar.add(calendar.DATE, 1);
        calendar.set(calendar.HOUR_OF_DAY, 0);
        calendar.set(calendar.MINUTE, 0);
        calendar.set(calendar.SECOND, 0);
        calendar.set(calendar.MILLISECOND, 0);
        return calendar.getTimeInMillis();
    }

    public static String formatDay(Date date) {
        DateFormat df = new SimpleDateFormat("yyyyMMdd");
        return df.format(date);
    }

    /**
     * 获取本周的周一日期
     * @return date
     */
    public static Date getMondayThisWeek() {
        Date todayStart = getTodayStartTime();
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(todayStart);
        calendar.setFirstDayOfWeek(Calendar.MONDAY);
        calendar.set(Calendar.DAY_OF_WEEK, Calendar.MONDAY);
        return calendar.getTime();
    }

    /**
     * 获取上周周一的日期
     * @return date
     */
    public static Date getPreMonday() {
        Date thisMonday = getMondayThisWeek();
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(thisMonday);
        calendar.add(Calendar.DATE, -7);
        return calendar.getTime();
    }

    /**
     * 时间转为分钟数，时间格式为HH:MM
     * @param time 字符串时间
     * @return 分钟数
     */
    public static Integer parseTimeMinute(String time) {
        Integer _time = 0;
        String[] aryTime = time.split(":");
        if (aryTime != null && aryTime.length == 2) {
            Integer hour = Integer.parseInt(aryTime[0]);
            Integer minute = Integer.parseInt(aryTime[1]);
            _time = hour * 60 + minute;
        }

        return _time;
    }

    /**
     * 时间转为毫秒数，时间格式为HH:MM
     * @param time 字符串时间
     * @return 毫秒数
     */
    public static Long parseTimeMillis(String time) {
        return parseTimeMinute(time) * 60 * 1000L;
    }

    public static void main(String a[]) {
//	     System.out.println("上季度开始:" + getPreviousQuarterStart(System.currentTimeMillis()));
//	     System.out.println("上季度开始:" + getPreviousQuarterEnd(System.currentTimeMillis()));
        Long now = System.currentTimeMillis();
        System.out.println("转为时分：" + DateUtil.format(now, DateUtil.FMT_H_M));
    }
}
